package com.t3.anistory
{
	import com.t3.animation.*;
	import com.t3.client.T3Client;
	import com.t3.display.StageObject;
	import com.t3.display.Thumbnail;
	import com.t3.events.*;
	import com.t3.fx.DropArea;
	import com.t3.tuio.TUIOCursor;
	import com.t3.tuio.TUIOEvent;
	import com.t3.tuio.TUIOTrail;
	
	import flash.display.Bitmap;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Shape;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	public class Sketchbook extends DropArea
	{
		protected var _sketch:StageObject;
		protected var _bmp:Thumbnail;
		protected var _thumb:Thumbnail;
		 
		protected var _pointAnimation:PointAnimation;
		protected var _hlAnimation:HighlightAnimation;
		
		protected var _sketchlines:Array = new Array();
		
		protected var _sketchMask:Shape;
		protected var _animMask:Shape;
		
		protected var _recording:Boolean = false;
		
		public function Sketchbook( bounds:Rectangle ):void
		{
			super( bounds, TUIOCursor, 0xFFFFFF, 0 );
            	
			_sketchMask = getMask( bounds );
			_animMask = getMask( bounds );
			
			_sketch = new StageObject();
			_sketch.graphics.beginFill( 0xFFFFFF, 0 );
			_sketch.graphics.drawRect( 0, 0, bounds.width, bounds.height );
			_sketch.graphics.endFill();
			_sketch.mask = _sketchMask;
			_sketch.stageLoc = this.stageLoc;
			
			_bmp = new Thumbnail( bounds, _sketch, 1, false, true, false ); 
			
			_pointAnimation = new PointAnimation( bounds, T3Client._framerate );
			_pointAnimation.addEventListener( AnimationEvent.ANIMATION_FINISH, animationFinished );
			_pointAnimation.mask = _animMask; 
			
			_thumb = new Thumbnail( bounds, _bmp, 1/8, true, true, true );
			
			_hlAnimation = new HighlightAnimation( bounds, _thumb.bitmapData );
			_hlAnimation.addEventListener( AnimationEvent.ANIMATION_FINISH, animationFinished ); 
			
			this.addChild( _bmp );
			this.addChild( _sketch );
			this.addChild( _animMask );
			this.addChild( _sketchMask );			
		}
		
		private function getMask( bounds:Rectangle ):Shape
		{
			var mask:Shape = new Shape();
			mask.graphics.beginFill( 0xFFFFFF, 0.6 );
			mask.graphics.drawRect( 0, 0, bounds.width, bounds.height );
			mask.graphics.endFill();
			
			return mask;
		}
		
		public function addCursor( event:TUIOEvent ):void
		{			
			if( !animating && !recording && event.point is TUIOTrail && hitObject.hitTestPoint( event.xStage, event.yStage ) )
			{ 
				var cursor:TUIOTrail = (TUIOTrail) (event.point);
				
				var line:Sketchline = new Sketchline();
				line.init( cursor.color, cursor.points );
				_sketchlines.push( line );
				
				cursor.addEventListener( TUIOEvent.REMOVE_TUIO_CUR, removeCursor );
				
				_sketch.addChild( cursor );
			}
			else if( recording )
			{
				highlightAnimation.addHighlight( new Point( event.xStage, event.yStage ) );
			}
		}
		
		private function removeCursor( event:TUIOEvent ):void
		{
			_bmp.updateThumb();
			
			event.target.removeEventListener( TUIOEvent.REMOVE_TUIO_CUR, removeCursor );
			
			remove( event.target as TUIOTrail, _sketch );
		}	
		
		public function sketchSprite( lines:Array ):void
		{	
			var bm:Bitmap = new Bitmap();
			
			for ( var e:uint = 0; e < lines.length; e++ )
			{
					_sketch.graphics.lineStyle( 20, lines[e].color );
					_sketchlines.push( lines[e] ); 
					
					_sketch.graphics.moveTo( lines[e].points[0].x - stageX, lines[e].points[0].y - stageY );
					for ( var a:uint = 1; a < lines[e].points.length; a++ )
					{
						var point:Point = new Point ( lines[e].points[a].x-stageX, lines[e].points[a].y-stageY ) ;
						_sketch.graphics.lineTo( point.x, point.y );
						_sketch.graphics.moveTo( point.x, point.y );	
					}
			}
			
			_bmp.updateThumb();
			_sketch.graphics.clear();
		}
		
		public function startAnimation():void
		{
			if( _hlAnimation.highlights.length > 0 )
			{
				startHighlightAnimation();
			}
			else
			{
				startPointAnimation();
			}
		}
		
		public function startPointAnimation():void
		{
			if( animating )
			{
				stopAnimation();
				return;
			}
			
			remove( _bmp, this );
			remove( _sketch, this );
			remove( _hlAnimation, this );
			
			this.addChild( _pointAnimation );
						
			_pointAnimation.animatedObjects = _sketchlines;
			_pointAnimation.start();
		}
		
		public function startHighlightAnimation():void
		{
			if( animating )
			{
				stopAnimation();
				return;
			}
			
			remove( _bmp, this );
			remove( _sketch, this );
			remove( _pointAnimation, this );
			
			_pointAnimation.reset();
			
			this.addChild( _hlAnimation );
			
			_hlAnimation.bitmapData = _bmp.bitmapData;
			_hlAnimation.start();
		}
		
		public function stopAnimation():void
		{
			remove( _pointAnimation, this );
			remove( _hlAnimation, this );
			
			this.addChild( _bmp );
			this.addChild( _sketch );
			
			_sketch.stageLoc = this.stageLoc;
			
			if( pointAnimation.running )
			{
				pointAnimation.reset();
			}
			
			if( highlightAnimation.running )
			{
				highlightAnimation.reset();
			}
		}
		
		public function startRecording():void
		{
			remove( _bmp, this );
			remove( _sketch, this );
			remove( _pointAnimation, this );
			
			_pointAnimation.reset();
			
			_hlAnimation.reset();			
			_hlAnimation.bitmapData = _bmp.bitmapData;
			_hlAnimation.startRecording();
			
			this.addChild( _hlAnimation );
			
			_recording = true;
		}
		
		public function stopRecording():void
		{
			stopAnimation();
			
			if( recording )
			{			
				_hlAnimation.stopRecording();
				_pointAnimation.duration = _hlAnimation.duration;
				_recording = false;
			}			
		}
		
		private function animationFinished( event:AnimationEvent ):void
		{
			stopAnimation();
		}
		
		private function remove( dob:DisplayObject, doc:DisplayObjectContainer ):void
		{
			if( doc.contains( dob ) )
			{
				doc.removeChild( dob );
			}
		}
		
		public function get recording():Boolean
		{
			return _recording;
		}
		
		public function get animating():Boolean
		{
			return pointAnimation.running || highlightAnimation.running;
		}
		
		public function set color( color:Number ):void
		{
			this._color = color;
		}
		
		public function get color():Number
		{
			return _color;
		}
		
		public function get sketchlines():Array
		{
			return _sketchlines;
		}
		
		public function set sketchlines( lines:Array ):void
		{
			this._sketchlines = lines;
		}
		
		public function get thumbnail():Thumbnail
		{
			return _thumb;
		}
		
		public function get highlightAnimation():HighlightAnimation
		{
			return this._hlAnimation;
		}
		
		public function get pointAnimation():PointAnimation
		{
			return this._pointAnimation;
		}		
		
		public override function get hitObject():DisplayObject
		{
			return this._bmp;
		}
	}
}
